<script setup>
import { onMounted, onUnmounted, ref, nextTick, reactive } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import { ElForm, ElNotification } from "element-plus";
import { getCenter } from "@/views/map/utils/index";
import { v4 } from "uuid";
import { cloneDeep } from "@pureadmin/utils";
const myAmap = ref(null);
const map = ref(null);
const mouseTool = ref(null);
const overlays = ref([]);
const markers = ref([]);
const loading = ref(true);
const drawStatus = ref(false);
const clickCount = ref(0);
const drawSetShow = ref(false);
const ruleForm = ref(null);
// 当前绘制完毕的图形的中心点
const center = ref([]);
// 当前绘制完毕的图形
const activeObj = ref(null);
// 当前鼠标移入 双击想操作的区域
const activeHandleObj = ref(null);
// 开启编辑的区块的返回值
const polyEditor = ref(null);
// 区块编辑状态
const editStatus = ref(false);
// 抽屉出来后表单状态 add edit
const formStatus = ref("add");
// 单击marker 出现编辑的active
const activeMarker = ref(null);
const form = reactive({
  data: {
    name: ""
  },
  rules: {
    name: [{ required: true, message: "区域名称不能为空", trigger: "blur" }]
  }
});
const cancel = () => {
  form.data.name = "";
  center.value = [];
  // activeObj.value.destroy();
  map.value.remove([activeObj.value]);
  clickCount.value = 0;
  mouseTool.value.close(false);
  drawStatus.value = false;
  nextTick(() => {
    ruleForm.value.clearValidate();
    drawSetShow.value = false;
  });
};
const beforeClose = d => {
  form.data.name = "";
  center.value = [];
  // activeObj.value.destroy();
  map.value.remove([activeObj.value]);
  clickCount.value = 0;
  mouseTool.value.close(false);
  drawStatus.value = false;
  ruleForm.value.clearValidate();
  drawSetShow.value = false;
  d();
};
const submit = () => {
  ruleForm.value.validate(async valid => {
    if (valid) {
      if (formStatus.value === "add") {
        let uuid = v4();
        let marker = new myAmap.value.Marker({
          map: map.value,
          // icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-' + (i + 1) + '.png',
          position: center.value,
          anchor: "bottom-center"
          // data: {
          //   uuid: uuid,
          //   form: cloneDeep(form.data)
          // }
        });
        marker.setLabel({
          direction: "right",
          offset: new myAmap.value.Pixel(10, 0), //设置文本标注偏移量
          content: `<div class='info'>${form.data.name}</div>` //设置文本标注内容
        });
        marker.setTitle(form.data.name);
        marker.setExtData({
          uuid: uuid,
          data: cloneDeep(form.data)
        });
        marker.on("click", e => {
          formStatus.value = "edit";
          drawFormHandle(marker);
        });
        activeObj.value.setExtData({
          uuid: uuid
        });
        // activeObj.value._opts.data = {
        //   uuid: uuid
        // };
        markers.value.push(marker);
        overlays.value.push(activeObj.value);

        clickCount.value = 0;
        drawStatus.value = false;
        mouseTool.value.close(false);
      } else {
        activeMarker.value.setLabel({
          direction: "right",
          offset: new myAmap.value.Pixel(10, 0), //设置文本标注偏移量
          content: `<div class='info'>${form.data.name}</div>` //设置文本标注内容
        });
        activeMarker.value.setTitle(form.data.name);
        let oriData = activeMarker.value.getExtData();
        activeMarker.value.setExtData({
          uuid: oriData.uuid,
          data: cloneDeep(form.data)
        });
      }
      drawSetShow.value = false;
    }
  });
};
const resetForm = () => {
  form.data.name = "";
  nextTick(() => {
    ruleForm.value.clearValidate();
  });
};
onMounted(() => {
  AMapLoader.load({
    key: "6c12e6d70ad9444d38cf9aafcc7a4393", // 申请好的Web端开发者Key，首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    plugins: ["AMap.MouseTool", "AMap.PolygonEditor"] // 需要使用的的插件列表，如比例尺'AMap.Scale'等
  })
    .then(AMap => {
      myAmap.value = AMap;
      map.value = new AMap.Map("map-container", {
        // 设置地图容器id
        viewMode: "2D", // 是否为3D地图模式
        zoom: 12, // 初始化地图级别
        center: [125.3245, 43.886841] // 初始化地图中心点位置
      });
      mouseTool.value = new AMap.MouseTool(map.value);
      mouseTool.value.on("draw", function (e) {
        let paths = e.obj.getPath();
        if (paths.length < 3) {
          clickCount.value = 0;
          map.value.remove([e.obj]);
          return;
        }
        if (paths.length !== clickCount.value) {
          map.value.remove([e.obj]);
          clickCount.value = 0;
          return;
        }
        center.value = getCenter(e.obj._opts.path);
        activeObj.value = e.obj;
        e.obj.on("mouseover", ev => {
          console.log(ev, "mouseover");
          tipShow.value = true;
          let oData = e.obj.getExtData();
          let marker = markers.value.find(z => {
            let zData = z.getExtData();
            return zData.uuid === oData.uuid;
          });
          tipData.data = marker.getExtData().data;
          ev.target.setOptions({
            fillOpacity: 0.7,
            fillColor: "#7bccc4",
            strokeColor: "#80d8ff"
          });
        });
        e.obj.on("mouseout", ev => {
          tipShow.value = false;
          console.log(ev, "mouseout");
          ev.target.setOptions({
            fillOpacity: 0.7,
            fillColor: "#00b0ff",
            strokeColor: "#80d8ff"
          });
        });
        e.obj.on("dblclick", ev => {
          if (editStatus.value) return;
          editStatus.value = true;
          activeHandleObj.value = e.obj;
          polyEditor.value = new myAmap.value.PolygonEditor(map.value, e.obj);
          polyEditor.value.open();
          polyEditor.value.on("addnode", function (event) {
            //切忌不要通过event的路径去拿path，tm路径居然会不定时变，
            //辛亏上线前发现了。可以用polygon.getPath()
          });

          polyEditor.value.on("adjust", function (event) {});

          polyEditor.value.on("removenode", function (event) {});

          polyEditor.value.on("end", function (event) {
            // event.target 即为编辑后的多边形对象
          });
        });
        drawSetShow.value = true;
        formStatus.value = "add";
        resetForm();
      });
      map.value.on("complete", function () {
        //地图图块加载完成后触发
        let allData = window.localStorage.getItem("_map_data_");
        let allDataObj = allData ? JSON.parse(allData) : null;
        if (allDataObj) {
          echoMapData(allDataObj);
        }
        loading.value = false;
        console.log("complete", "complete");
      });
      map.value.on("click", e => {
        if (drawStatus.value) {
          clickCount.value += 1;
        }
      });
      map.value.on("dblclick", e => {});
      map.value.on("rightclick", e => {});
    })
    .catch(e => {
      console.log(e);
    });
});
const draw = () => {
  drawStatus.value = true;
  clickCount.value = 0;
  mouseTool.value.polygon({
    fillOpacity: 0.7,
    fillColor: "#00b0ff",
    strokeColor: "#80d8ff"
    //同Polygon的Option设置
  });
};
const stopDraw = () => {
  if (clickCount.value > 0) {
    ElNotification({
      title: "系统提示",
      message: "请绘制完整图形!",
      type: "warning"
    });
    return;
  }
  clickCount.value = 0;
  drawStatus.value = false;
  mouseTool.value.close(false);
};
const clearAll = () => {
  map.value.remove(overlays.value);
  map.value.remove(markers.value);
  overlays.value = [];
  markers.value = [];
};
const stopEdit = () => {
  if (!editStatus.value) return;
  let paths = activeHandleObj.value.getPath();
  let areaData = activeHandleObj.value.getExtData();
  // 停止编辑后计算中心点 挪动marker
  let center = getCenter(paths.map(item => [item.lng, item.lat]));
  markers.value.forEach(item => {
    let moData = item.getExtData();
    if (moData.uuid === areaData.uuid) {
      item.setPosition(center);
    }
  });
  polyEditor.value && polyEditor.value.close();
  editStatus.value = false;
};
const saveAll = () => {
  if (markers.value.length && overlays.value.length) {
    // 保存 marker position  表单数据
    let mks = [];
    markers.value.forEach(item => {
      let z = {
        p: item.getPosition(),
        data: item.getExtData()
      };
      mks.push(z);
    });
    // 保存区块 paths  data
    let lays = [];
    overlays.value.forEach(item => {
      let z = {
        paths: item.getPath(),
        data: item.getExtData()
      };
      lays.push(z);
    });
    window.localStorage.setItem(
      "_map_data_",
      JSON.stringify({ m: mks, o: lays })
    );
  } else {
    window.localStorage.setItem("_map_data_", JSON.stringify({ m: [], o: [] }));
  }
};
const echoMapData = data => {
  if (data.o && data.o.length) {
    for (let i = 0; i < data.o.length; i++) {
      let item = data.o[i];
      let polygon = new myAmap.value.Polygon({
        path: item.paths,
        fillColor: "#00b0ff",
        strokeOpacity: 1,
        fillOpacity: 0.7,
        strokeColor: "#80d8ff",
        strokeWeight: 1,
        strokeStyle: "dashed",
        strokeDasharray: [5, 5]
      });
      polygon.on("mouseover", ev => {
        console.log(ev, "mouseover");
        tipShow.value = true;
        let oData = polygon.getExtData();
        let marker = markers.value.find(z => {
          let zData = z.getExtData();
          return zData.uuid === oData.uuid;
        });
        tipData.data = marker.getExtData().data;
        polygon.setOptions({
          fillOpacity: 0.7,
          fillColor: "#7bccc4",
          strokeColor: "#80d8ff"
        });
      });
      polygon.on("mouseout", ev => {
        console.log(ev, "mouseout");
        tipShow.value = false;
        polygon.setOptions({
          fillOpacity: 0.7,
          fillColor: "#00b0ff",
          strokeColor: "#80d8ff"
        });
      });
      polygon.on("dblclick", ev => {
        if (editStatus.value) return;
        editStatus.value = true;
        activeHandleObj.value = polygon;
        polyEditor.value = new myAmap.value.PolygonEditor(map.value, polygon);
        polyEditor.value.open();
        polyEditor.value.on("addnode", function (event) {
          //切忌不要通过event的路径去拿path，tm路径居然会不定时变，
          //辛亏上线前发现了。可以用polygon.getPath()
        });

        polyEditor.value.on("adjust", function (event) {});

        polyEditor.value.on("removenode", function (event) {});

        polyEditor.value.on("end", function (event) {
          // event.target 即为编辑后的多边形对象
        });
      });
      polygon.setExtData({
        uuid: item.data.uuid
      });
      map.value.add(polygon);
      overlays.value.push(polygon);
    }
    for (let i = 0; i < data.m.length; i++) {
      let item = data.m[i];
      let marker = new myAmap.value.Marker({
        map: map.value,
        // icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-' + (i + 1) + '.png',
        position: item.p,
        anchor: "bottom-center"
      });
      marker.setLabel({
        direction: "right",
        offset: new myAmap.value.Pixel(10, 0), //设置文本标注偏移量
        content: `<div class='info'>${item.data.data.name || ""}</div>` //设置文本标注内容
      });
      marker.setTitle(item.data.data.name);
      marker.on("click", e => {
        formStatus.value = "edit";
        drawFormHandle(marker);
      });
      marker.setExtData({
        uuid: item.data.uuid,
        data: item.data.data
      });
      markers.value.push(marker);
    }
  }
};
const drawFormHandle = marker => {
  let data = marker.getExtData();
  activeMarker.value = marker;
  drawSetShow.value = true;
  form.data = cloneDeep(data.data);
};
const delThis = () => {
  // 根据 activeMarker 删除 区域 marker
  let data = activeMarker.value.getExtData();
  let activeArea = overlays.value.find(item => {
    let aData = item.getExtData();
    if (aData.uuid === data.uuid) {
      return true;
    }
  });
  if (activeArea) {
    // 地图删除
    map.value.remove([activeMarker.value, activeArea]);
    // 数组删除
    let oIndex = overlays.value.findIndex(item => {
      return item.getExtData().uuid === data.uuid;
    });
    overlays.value.splice(oIndex, 1);
    let mIndex = markers.value.findIndex(item => {
      return item.getExtData().uuid === data.uuid;
    });
    markers.value.splice(mIndex, 1);
    activeMarker.value = null;
    activeObj.value = null;
    activeHandleObj.value = null;
    drawSetShow.value = false;
  }
};
const tipShow = ref(false);
const tipData = reactive({
  data: null
});
onUnmounted(() => {
  map.value?.destroy();
});
</script>

<template>
  <div v-loading="loading" class="main">
    <div class="absolute left-0 top-0 z-10">
      <el-button v-if="!drawStatus" type="primary" @click="draw"
        >绘制</el-button
      >
      <el-button v-if="drawStatus" type="primary" @click="stopDraw"
        >停止绘制</el-button
      >
      <el-button type="primary" @click="clearAll">清空所有</el-button>
      <el-button v-if="editStatus" type="primary" @click="stopEdit"
        >停止编辑</el-button
      >
      <el-button type="primary" @click="saveAll">保存所有</el-button>
    </div>
    <div v-if="tipShow" class="absolute right-0 top-0 z-10">
      <el-card>
        {{ tipData.data ? tipData.data.name : "无数据" }}
      </el-card>
    </div>
    <div id="map-container" />
    <el-drawer
      v-model="drawSetShow"
      title="区域信息设置"
      :close-on-click-modal="false"
      :before-close="beforeClose"
      size="20%"
    >
      <div>
        <el-form
          ref="ruleForm"
          label-width="80px"
          :model="form.data"
          :rules="form.rules"
        >
          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="区域名称" prop="name">
                <el-input v-model="form.data.name" placeholder="区域名称" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-popconfirm
            v-if="formStatus === 'edit'"
            width="200px"
            title="确定删除该区块吗？"
            @confirm="delThis"
          >
            <template #reference>
              <el-button type="danger"> 删除该区块 </el-button>
            </template>
          </el-popconfirm>
          <el-button v-if="formStatus === 'add'" @click="cancel"
            >取消</el-button
          >
          <el-button type="primary" @click="submit"> 确认 </el-button>
        </span>
      </template>
    </el-drawer>
  </div>
</template>

<style scoped lang="scss">
.main {
  position: relative;
  width: 100%;
  height: 100%;

  #map-container {
    position: relative;
    width: 100%;
    height: 100%;
  }
}
</style>
